package org.gw.ylc.base.service;

import com.wiscom.is.IdentityFactory;
import org.gw.ylc.base.model.UserInfo;
import org.gw.ylc.base.util.CryptoUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;

@Service
public class AuthenticateService implements InitializingBean {
	@Autowired
	private UserInfoService userInfoService;
	@Value("#{config['auth.mode']}")
	private String authMode = "db";
	@Value("#{config['auth.db.always']}")
	private String authDBAlways = "true";// 如果为true，那么在认证时总是会尝试db认证
	private boolean isIds = false;
	private String idsLoginURL;
	private String idsLogoutURL;

	/**
	 * 用户认证
	 * 
	 * @param request
	 * @param isDBAuthMode
	 * @return
	 */
	public List<UserInfo> authenticate(HttpServletRequest request,String app) {
		if (isIds) {
			List<UserInfo> users = iceAuthenticate(request,app);
			if (!CollectionUtils.isEmpty(users)) {
				return users;
			}
			if (authDBAlways.equals("true")) {
				return dbAuthenticate(request.getParameter("username"), request.getParameter("password"),app);
			} else {
				return users;
			}
		}
		return dbAuthenticate(request.getParameter("username"), request.getParameter("password"),app);
	}

	/**
	 * 数据库认证
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	private List<UserInfo> dbAuthenticate(String username, String password,String app) {
		List<UserInfo> users = userInfoService.getUserInfo(username, 1,app);
		// 即使是一个username对应多个userInfo，这多个userInfo的密码其实是一样的，因为试图里面是根据username是关联userInfoExt的密码的
		if (!CollectionUtils.isEmpty(users) && users.get(0).getPassword() != null) {
			try {
				if (CryptoUtils.verifyHash(password, users.get(0).getPassword()))
					return users;
			} catch (Exception e) {
			}
		}
		return null;
	}

	/**
	 * IDS认证
	 * 
	 * @param request
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private List<UserInfo> iceAuthenticate(HttpServletRequest request,String app) {
		IdentityFactory factory = initICE();
		String userId = null; // 用户登录 id
		// 取 cookie
		String decodedCookieValue = null;
		Cookie[] all_cookies = request.getCookies();
		if (all_cookies == null) {
			return null;
		}
		for (int i = 0; i < all_cookies.length; i++) {
			Cookie myCookie = all_cookies[i];
			// 单点登录 cookie 名称 "iPlanetDirectoryPro"
			if (myCookie.getName().equals("iPlanetDirectoryPro")) {
				try {
					decodedCookieValue = URLDecoder.decode(myCookie.getValue(), "utf-8");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				break;
			}
		}
		// 取当前用户属性,请使用工号、学号作为判断用户是学生还是教师的依据
		userId = factory.getIdentityManager().getCurrentUser(decodedCookieValue); // 用户登录
		if (StringUtils.isEmpty(userId)) {
			return null;
		}
		List<UserInfo> userInfos = userInfoService.getUserInfo(userId, 1,app);
		if (CollectionUtils.isEmpty(userInfos)) {
			throw new IllegalArgumentException(userId + "，该帐号不存在");
		}
		return userInfos;
	}

	/**
	 * 构造IDS登录地址
	 * 
	 * @param gotoUrl
	 * @param gotoOnFailUrl
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public String getICELoginUrl(String gotoUrl, String gotoOnFailUrl) throws UnsupportedEncodingException {
		if (idsLoginURL == null) {
			idsLoginURL = initICE().getIdentityManager().getLoginURL();
		}
		String loginURL = idsLoginURL + "?goto=" + java.net.URLEncoder.encode(gotoUrl, "utf-8");
		loginURL += "&gotoOnFail=" + java.net.URLEncoder.encode(gotoOnFailUrl, "utf-8");
		return loginURL;
	}

	public String getICELogoutUrl(String gotoUrl) throws UnsupportedEncodingException {
		if (idsLogoutURL == null) {
			idsLogoutURL = initICE().getIdentityManager().getLogoutURL();
		}
		String logoutURL = idsLogoutURL + "?goto=" + java.net.URLEncoder.encode(gotoUrl, "utf-8");
		return logoutURL;
	}

	private IdentityFactory initICE() {
		try {
			File file = ResourceUtils.getFile("classpath:client.properties");
			return IdentityFactory.createFactory(file.getCanonicalPath());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		if ("ids".equalsIgnoreCase(authMode)) {
			isIds = true;
			IdentityFactory factory = initICE();
			idsLoginURL = factory.getIdentityManager().getLoginURL();
			idsLogoutURL = factory.getIdentityManager().getLogoutURL();
		}
	}
}
